package com.ck.print.demo.printbridge;

import com.ck.print.demo.printbridge.message.handler.center.QueryAgentMacHandle;
import lombok.extern.slf4j.Slf4j;

import java.net.URISyntaxException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 连接管理器管理连接打印的cloud和QzTray,提供打印消息的透明传输
 */
@Slf4j
public class ClientManager {

    private static ClientManager Instance;
    private AppConfig config;
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    /**
     * 存放打印消息的cloud和QzTray的连接,key:serverCloud connect, value:serverQzTray connect
     */
    private final Map<PrintWebSocketClient, PrintWebSocketClient> clients = new ConcurrentHashMap<>(4);

    public synchronized static ClientManager getInstance() {
        if (Instance == null) {
            Instance = new ClientManager();
        }
        return Instance;
    }

    /**
     * 从配置中读取打印中心的ip地址和端口号
     */
    public void init() throws URISyntaxException {
        ConfigPropertyMapping mapping = new ConfigPropertyMapping("ServerConfig.properties");
        this.config = mapping.mapToObject(AppConfig.class);


        PrintWebSocketClient cloudClient = new PrintWebSocketClient("ws://" + config.getPrintcenterServerIp() + ":" + config.getPrintcenterServerPort()+"/ws/agent", "cloudClient", scheduler);
        PrintWebSocketClient qzTrayClient = new QzTrayWebSocketClient("ws://" + config.getPrintcenterQzTrayIp() + ":" + config.getPrintcenterQzTrayPort(), "qzTrayClient", scheduler);

        //初始化映射通道
        cloudClient.initChannel(qzTrayClient, new QueryAgentMacHandle(cloudClient.getClientName()));
        qzTrayClient.initChannel(cloudClient);

        qzTrayClient.connect();
        cloudClient.connect();

        clients.put(cloudClient, qzTrayClient);
        scheduler.scheduleWithFixedDelay(() -> {
            log.info("{} state :{}", cloudClient.getClientName(), cloudClient.isOpen());
            log.info("{} state :{}", qzTrayClient.getClientName(), qzTrayClient.isOpen());
        }, 10, 10, TimeUnit.SECONDS);
    }

    private void shutdown() {
        scheduler.shutdown();
        clients.forEach((cloud, qzTray) -> {
            try {
                if(cloud.isOpen()) {
                    cloud.close();
                }
            }finally {

            }
            try {
                if(qzTray.isOpen()) {
                    qzTray.close();
                }
            }finally {

            }
        });
    }


    /**
     * test
     * @param args
     * @throws URISyntaxException
     */
    public static void main(String[] args) throws URISyntaxException {
        ClientManager.getInstance().init();
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            ClientManager.getInstance().shutdown();
        }));
    }
}
